"""
gRPC音频服务实现
"""

import os
import uuid
from concurrent import futures

import grpc

import config
# 导入返回码枚举
from src.constants.return_codes import ReturnCode, TTSErrorCode, STTErrorCode, FileErrorCode, VPErrorCode
# 导入返回码工具类
from src.constants.return_codes import ReturnCodes as RC
# 导入STT服务
from src.stt.stt_service import STTService
# 导入TTS服务
from src.tts.tts_service import TTSService
# 导入日志工具
from src.utils.logger import get_logger, set_request_id_for_logger
# 导入声纹识别服务
from src.voiceprint.voiceprint_service import VoiceprintService
# 导入响应工厂类
from .response_factory import ResponseFactory

# 获取logger实例
logger = get_logger(__name__)

# 导入生成的gRPC代码
from . import audio_service_pb2_grpc


class AudioServiceServicer(audio_service_pb2_grpc.AudioServiceServicer):
    """
    音频服务gRPC服务器实现
    """

    def __init__(self):
        """
        初始化音频服务
        """
        logger.info("初始化音频服务")
        # 初始化STT服务实例
        self.stt_service = STTService()
        # 初始化TTS服务实例
        self.tts_service = TTSService()
        # 初始化声纹识别服务实例
        self.voiceprint_service = VoiceprintService()
        logger.info("音频服务初始化完成")

    def TextToSpeech(self, request, context):
        """文本转语音接口"""
        # 获取或生成请求ID
        request_id = request.request_id if request.request_id else str(uuid.uuid4())
        # 设置日志的请求ID
        set_request_id_for_logger(request_id)

        # 记录请求日志
        logger.info("收到TTS请求: text=%s, voice=%s, request_id=%s",
                    request.text, request.voice, request_id)

        # 调用TTS服务进行文本转语音
        code, result = self.tts_service.text_to_speech(
            request.text, request.voice)
        # 获取生成的音频文件路径
        audio_file_path = result.get("audio_file")
        
        # 检查处理是否成功
        if RC.is_success(code.code):
            # 读取音频文件内容
            try:
                with open(audio_file_path, 'rb') as audio_file:
                    audio_data = audio_file.read()

                # 记录响应结果日志
                logger.info("TTS响应结果: code=%d, result=%s", code.code, str(result))

                # 使用工厂类创建成功响应
                # 构造更完整的result
                response = ResponseFactory.create_tts_response(
                    ReturnCode.SUCCESS,
                    audio_data=audio_data,
                    request_id=request_id,
                    text=request.text,
                    voice=request.voice,
                    selected_voice=result.get("selected_voice", request.voice or "default")
                )

                # 删除临时音频文件
                try:
                    os.remove(audio_file_path)
                    logger.info("已删除临时音频文件: %s", audio_file_path)
                except Exception as e:
                    logger.warning("删除临时音频文件失败: %s", str(e))

                return response
            except Exception as e:
                logger.error("读取音频文件失败: %s", str(e))
                # 返回文件读取错误响应
                return ResponseFactory.create_tts_response(
                    FileErrorCode.READ_ERROR,
                    request_id=request_id
                )
        else:
            # 记录错误响应日志
            error_msg = result if isinstance(result, str) else result.get('error', '未知错误')
            logger.error("TTS错误响应: code=%d, msg=%s", code.code, error_msg)
            # 返回TTS转换失败响应
            return ResponseFactory.create_tts_response(
                TTSErrorCode.CONVERSION_FAILED,
                request_id=request_id
            )

    def SpeechToText(self, request, context):
        """语音转文本接口"""
        # 获取或生成请求ID
        request_id = request.request_id if request.request_id else str(uuid.uuid4())
        # 设置日志的请求ID
        set_request_id_for_logger(request_id)

        # 记录请求日志
        logger.info("收到STT请求: language=%s, request_id=%s", request.language, request_id)

        # 保存临时音频文件
        temp_file_name = f"temp_audio_{request_id}.wav"
        temp_audio_path = os.path.join(os.getcwd(), temp_file_name)

        try:
            # 保存音频数据到临时文件
            with open(temp_audio_path, 'wb') as f:
                f.write(request.audio_data)

            logger.info("已保存临时音频文件: %s", temp_audio_path)

            # 使用并发STT管理器处理
            from src.stt.concurrent_stt_manager import process_audio_concurrently
            code, result_info = process_audio_concurrently(
                temp_audio_path,
                language=request.language if request.language else None,
                timeout=config.STT_TIMEOUT
            )

            # 使用工厂类创建响应
            if RC.is_success(code.code):
                # 创建成功响应
                response = ResponseFactory.create_stt_response(
                    ReturnCode.SUCCESS,
                    text=result_info.get("text", ""),
                    request_id=request_id,
                    audio_file=result_info.get("audio_file", temp_audio_path),
                    language=result_info.get("language", request.language or ""),
                    detected_language=result_info.get("detected_language", "unknown")
                )
            else:
                # 创建失败响应
                response = ResponseFactory.create_stt_response(
                    STTErrorCode.CONVERSION_FAILED,
                    request_id=request_id
                )

            logger.info("STT响应结果: code=%d, result=%s",
                        code.code if hasattr(code, 'code') else int(code), str(result_info))
            return response

        except futures.TimeoutError:
            logger.error("STT处理超时")
            # 设置gRPC超时状态
            context.set_code(grpc.StatusCode.DEADLINE_EXCEEDED)
            context.set_details("STT处理超时")
            # 返回超时错误响应
            return ResponseFactory.create_stt_response(
                STTErrorCode.STT_TIME_OUT,
                request_id=request_id
            )
        except Exception as e:
            logger.error("STT处理异常: %s", str(e))
            # 返回转换失败响应
            return ResponseFactory.create_stt_response(
                STTErrorCode.CONVERSION_FAILED,
                request_id=request_id
            )

        finally:
            # 清理临时文件
            try:
                if os.path.exists(temp_audio_path):
                    os.remove(temp_audio_path)
                    logger.info("已删除临时音频文件: %s", temp_audio_path)
            except Exception as e:
                logger.warning("删除临时文件失败: %s", str(e))

    def ExtractVoiceprint(self, request, context):
        """声纹识别接口"""
        # 获取或生成请求ID
        request_id = request.request_id if request.request_id else str(uuid.uuid4())
        # 设置日志的请求ID
        set_request_id_for_logger(request_id)

        # 记录请求日志
        logger.info("收到声纹识别请求: request_id=%s", request_id)

        # 保存临时音频文件
        temp_audio_file = f"temp_voiceprint_{request_id}.wav"
        try:
            with open(temp_audio_file, "wb") as f:
                f.write(request.audio_data)
            logger.info("已保存临时音频文件: %s", temp_audio_file)
        except Exception as e:
            logger.error("保存音频文件失败: %s", str(e))
            # 返回文件写入错误响应
            return ResponseFactory.create_voiceprint_response(
                FileErrorCode.WRITE_ERROR,
                request_id=request_id
            )

        # 调用声纹识别服务
        code, result = self.voiceprint_service.extract_voiceprint(
            temp_audio_file)

        # 删除临时音频文件
        try:
            os.remove(temp_audio_file)
            logger.info("已删除临时音频文件: %s", temp_audio_file)
        except Exception as e:
            logger.warning("删除临时音频文件失败: %s", str(e))

        # 检查处理是否成功
        if RC.is_success(code.code):
            # 记录响应结果日志
            logger.info("声纹识别响应结果: code=%d, result=%s", code.code, str(result))
            # 返回成功响应
            return ResponseFactory.create_voiceprint_response(
                ReturnCode.SUCCESS,
                request_id=request_id,
                voiceprint_id=result.get("voiceprint_id", "")
            )
        else:
            # 记录错误响应日志
            error_msg = result if isinstance(result, str) else result.get('error', '未知错误')
            logger.error("声纹识别错误响应: code=%d, msg=%s", code.code, error_msg)
            # 返回声纹识别失败响应
            return ResponseFactory.create_voiceprint_response(
                VPErrorCode.CONVERSION_FAILED,
                request_id=request_id,
            )


def serve():
    """
    启动gRPC服务器
    """
    # 创建gRPC服务器
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=config.GRPC_MAX_WORKERS))

    # 注册服务
    audio_service_pb2_grpc.add_AudioServiceServicer_to_server(
        AudioServiceServicer(), server)

    # 绑定端口
    server.add_insecure_port('[::]:50051')

    # 启动服务器
    logger.info("启动gRPC服务器，监听端口50051")
    server.start()
    logger.info("gRPC服务器启动成功")

    try:
        # 等待服务器终止
        server.wait_for_termination()
    except KeyboardInterrupt:
        logger.info("收到键盘中断信号，正在关闭gRPC服务器")
        server.stop(0)
        logger.info("gRPC服务器已关闭")


if __name__ == '__main__':
    serve()
